#include "Headers.h"
#include "Application.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
HWND g_hWndMain;
LPCTSTR lpszClass = TEXT("Game");

const int SKIP_TICK = 1000/60;


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
	LPSTR lpszCmdParam, int nCmdShow)
{
	HWND hWnd;
	MSG Message;
	WNDCLASS WndClass;
	ZeroMemory((void*)&WndClass, sizeof(WNDCLASS));
	g_hInst = hInstance;

	WndClass.cbClsExtra = 0;
	WndClass.cbWndExtra = 0;
	WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	WndClass.hInstance = hInstance;
	WndClass.lpfnWndProc = WndProc;
	WndClass.lpszClassName = lpszClass;
	WndClass.lpszMenuName = NULL;
	WndClass.style = CS_HREDRAW | CS_VREDRAW;
	RegisterClass(&WndClass);

	hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW^WS_THICKFRAME^WS_MAXIMIZEBOX,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, (HMENU)NULL, hInstance, NULL);
	ShowWindow(hWnd, nCmdShow);
	ZeroMemory((void*)&Message, sizeof(MSG));

	if(Application()->Initiallize() == false)
	{
		Application()->Uninitialize();
		return -1;
	}
	
	while(Message.message != WM_QUIT)
	{
		if(PeekMessage(&Message, NULL, 0, 0, PM_NOREMOVE))
		{
			if(GetMessage(&Message, NULL, 0, 0))
			{	
				TranslateMessage(&Message);
				DispatchMessage(&Message);
			}
		}
		else if(GetForegroundWindow() == g_hWndMain)
		{
			static DWORD NextTick = GetTickCount();
			if(GetTickCount() > NextTick)
			{
				Application()->Process();
				TimeManager()->Process();
				NextTick += SKIP_TICK;
			}
			else
			{
				Sleep(1);
			}
		}
	}

	Application()->Uninitialize();
	Application()->DestroyInstance();
	InputManager()->Uninitialize();
	InputManager()->DestroyInstance();
	FILEMANAGER()->DestroyInstance();
	CAMERA()->DestroyInstance();
	return (int)Message.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
	HDC hdc, MemDC;
	PAINTSTRUCT ps;
	RECT crt;

	switch(iMessage)
	{
	case WM_CREATE:
		g_hWndMain = hWnd;
		SetRect(&crt, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
		AdjustWindowRect(&crt, WS_OVERLAPPEDWINDOW^WS_THICKFRAME^WS_MAXIMIZEBOX, false);
		SetWindowPos(hWnd, NULL, 0, 0, crt.right-crt.left, crt.bottom-crt.top, 
			SWP_NOMOVE | SWP_NOZORDER);
		SetTimer(hWnd, 1, 10, NULL);
		return 0;
	case WM_TIMER:
		InvalidateRect(hWnd, NULL, false);
		UpdateWindow(hWnd);
		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		HBITMAP memBit;
		HBITMAP OldBit;
		RECT crt;

		MemDC = CreateCompatibleDC(hdc);
		GetClientRect(hWnd, &crt);

		memBit = CreateCompatibleBitmap(hdc, crt.right-crt.left, crt.bottom-crt.top);
		OldBit = (HBITMAP)SelectObject(MemDC, memBit);

		FillRect(MemDC, &crt, (HBRUSH)GetStockObject(BLACK_BRUSH));
		Application()->Render(MemDC);

		BitBlt(hdc, crt.left, crt.top, crt.right-crt.left, crt.bottom-crt.top,
			MemDC, 0, 0, SRCCOPY);

		SelectObject(MemDC, OldBit);
		DeleteObject(memBit);
		DeleteDC(MemDC);

		EndPaint(hWnd, &ps);

		//TimeManager()->Process();
		return 0;
	case WM_DESTROY:
		KillTimer(hWnd, 1);
		PostQuitMessage(0);
		return 0;
	}
	return (DefWindowProc(hWnd, iMessage, wParam, lParam));
}